import request from '@/utils/request'
import type { ResponseData } from 'dto/globalDto.ts'
import type { loginInDto, LoginOutDto } from 'dto/login/loginDto.ts'

//@ts-ignore
import CryptoJS from 'crypto-js'
import JSON5 from 'json5'
import dayjs from 'dayjs'
import JSEncrypt from 'jsencrypt'
//@ts-ignore
import smCrypto from 'sm-crypto'
import { v4 as uuidv4 } from 'uuid'
//@ts-ignore
import md5 from 'md5'

enum API {
  LOGIN_URL = '/user/login',
}

/**
 * 登录
 * @param {loginInDto} data 账号和密码
 * @returns {string} token
 */
export const userLogin = (data: loginInDto) => {
  const password = md5Password(data)
  data.password = password
  return request.post<any, ResponseData<LoginOutDto>>(API.LOGIN_URL, data)
}

/**
 * 对称加密
 * @param {string} plainStr
 * @returns {string}
 */
export function encryptPassword(plainStr: string) {
  // RSA公钥
  const publicKey = import.meta.env.VITE_APP_PUBLICKEY
  console.log('公钥：', publicKey)
  const sm4 = smCrypto.sm4
  // 获取当前时间字符串，格式为 YYYYMMDDHHmmss
  const dateTimeStr = dayjs().format('YYYYMMDDHHmmss')
  // 生成一个32字节的随机字符串
  const randomStr = CryptoJS.lib.WordArray.random(32).toString()
  // 使用 UUID + 当前时间字符串 + 32位随机字符串 生成 AES 密钥的源字符串
  const aesKeySource = `${uuidv4()}-${dateTimeStr}-${randomStr}`
  // 对源字符串进行 MD5 哈希，生成 AES 密钥
  const aesKey = CryptoJS.MD5(aesKeySource).toString(CryptoJS.enc.Hex)
  // 将 AES 密钥转换为 Base64 编码
  const base64AesKey = CryptoJS.enc.Base64.stringify(
    CryptoJS.enc.Hex.parse(aesKey),
  )
  // 获取当前日期字符串，格式为 YYYYMMDD
  const dateStr = dayjs().format('YYYYMMDD')
  // 使用 Base64 编码的 AES 密钥和当前日期字符串生成 IV（初始化向量）
  const iv = md5(`${base64AesKey}${dateStr}`)
  // 使用 AES 密钥和 IV 对明文字符串进行 AES 加密
  const data = CryptoJS.AES.encrypt(plainStr, CryptoJS.enc.Hex.parse(aesKey), {
    iv: CryptoJS.enc.Hex.parse(iv),
    mode: CryptoJS.mode.CFB,
    padding: CryptoJS.pad.Pkcs7,
  }).ciphertext.toString(CryptoJS.enc.Hex)
  // 创建 RSA 加密器并设置公钥
  let encryptor = new JSEncrypt()
  encryptor.setPublicKey(publicKey)
  // 使用 RSA 公钥对 Base64 编码的 AES 密钥进行加密
  const key = encryptor.encrypt(base64AesKey)
  // 组装请求数据对象
  let reqDataObj = { key, data }
  // 将请求数据对象转换为 JSON 字符串
  let jsonStr = JSON5.stringify(reqDataObj)
  // 使用当前日期字符串的 MD5 哈希值作为 SM4 密钥
  const sm4Key = md5(dateStr)
  // 使用 SM4 密钥对 JSON 字符串进行加密
  const sm4Encrypted = sm4.encrypt(jsonStr, sm4Key)
  // 返回加密后的字符串
  return sm4Encrypted
}

export function md5Password(data: loginInDto) {
  const pwd = encryptPassword(data.password + ':' + data.username)
  return pwd
}
